package org.dna.wickwtui.activities;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.wicket.Component;
import org.apache.wicket.datetime.markup.html.form.DateTextField;
import org.apache.wicket.extensions.yui.calendar.DatePicker;
import org.apache.wicket.feedback.ContainerFeedbackMessageFilter;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.form.validation.FormComponentFeedbackBorder;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.validation.validator.MinimumValidator;
import org.apache.wicket.validation.validator.RangeValidator;
import org.dna.MetroApplication;
import org.dna.metronomo.persistence.Activity;
import org.dna.metronomo.persistence.IActivityDAO;
import org.dna.metronomo.persistence.Job;
import org.dna.uimodel.LoadableActivityModel;
import org.dna.uimodel.LoadableJobModel;
import org.dna.uimodel.MenuItem;
import org.dna.uimodel.SelectableActivity;
import org.dna.wickwtui.jobs.JobListPanel;
import org.dna.wickwtui.jobs.ManageJobPage;
import org.dna.wickwtui.users.IContextMenuProvider;
import org.dna.wickwtui.utils.AtLeastOneValidator;

public class ActivityDetailsPanel extends Panel implements IContextMenuProvider {

	private static final long serialVersionUID = 6174871448930055063L;

	private boolean m_editMode = false;

	private Button btnSumbit;
	private TextField<String> tfName;
	private TextArea<String> taDescription;
	private IModel<Activity> m_actModel;
	private Form<Activity> m_form;
	private TextField<Integer> tfDays;
	private TextField<Integer> tfHours;
	private DateTextField tfEstimatedTime;
	
	//this store of unboxing in necessary to avoid users the duty to insert all 
	//time fields.
	protected Integer daysU;
	protected Integer hoursU;

	public ActivityDetailsPanel(String id) {
		super(id);
		m_editMode = false;
		m_actModel = new Model<Activity>(new SelectableActivity(new Activity()));
		initComponents();
	}

	public ActivityDetailsPanel(String id, SelectableActivity editable) {
		super(id);
		m_editMode = true;
		if (editable != null) {
			m_actModel = new LoadableActivityModel(editable);
		}
		initComponents();
	}

	@SuppressWarnings( { "serial" })
	private void initComponents() {
		m_form = new Form<Activity>("form") {
			@Override
			protected void onSubmit() {
				IActivityDAO dao = MetroApplication.get().getActivityDAO();
				Activity activity = getModelObject();
				if (daysU != null) activity.getEstimatedEffort().setDays(daysU);
				if (hoursU != null) activity.getEstimatedEffort().setHours(hoursU);
				if (m_editMode) {
					dao.update(activity);
				} else {
					dao.addNewActivity(activity);
				}
			}
		};
		m_form.setModel(new CompoundPropertyModel<Activity>(m_actModel));
		add(m_form);
		tfName = new TextField<String>("name");
		taDescription = new TextArea<String>("description");
		tfDays = new TextField<Integer>("days", new PropertyModel(this, "daysU"));
		tfDays.add(new MinimumValidator<Integer>(0));
		tfHours = new TextField<Integer>("hours", new PropertyModel(this, "hoursU"));
		tfHours.add(new RangeValidator<Integer>(0, 23));
		
		String submitLabel = "Update";
		final WebMarkupContainer wmc = new WebMarkupContainer("wmc");
		add(wmc);
		if (!m_editMode) {
			submitLabel = "Create";
			tfName.setRequired(true);
			taDescription.setRequired(true);
			wmc.setVisible(false);
		} else {
			wmc.setVisible(true);
		}
		btnSumbit = new Button("button", new Model<String>(submitLabel));
		m_form.add(btnSumbit);
		m_form.add(new FormComponentFeedbackBorder("border").add(tfName));
		m_form.add(taDescription);
		m_form.add(tfDays);
		m_form.add(tfHours);
		
		tfEstimatedTime = DateTextField.forShortStyle("estimatedStart");
		tfEstimatedTime.add(new DatePicker());
		m_form.add(tfEstimatedTime);
		
		Activity activity = m_actModel.getObject();
		if (activity.getEstimatedEffort().getDays() != 0) daysU = activity.getEstimatedEffort().getDays();
		if (activity.getEstimatedEffort().getHours() != 0) hoursU = activity.getEstimatedEffort().getHours();
		
		m_form.add(new AtLeastOneValidator(tfDays, tfHours));
		add(new FeedbackPanel("feedback", new ContainerFeedbackMessageFilter(m_form)));
		
		List<IModel<Job>>  modelJob = prepareLoadableJobListModel(m_actModel.getObject().getJobs());
		wmc.add(new JobListPanel("jobs", modelJob));
	}
	
	private List<IModel<Job>> prepareLoadableJobListModel(List<Job> jobs) {
		if (jobs == null) {
			return new ArrayList<IModel<Job>>(); //return empty model's list 
		}
		List<IModel<Job>> modelJobs = new ArrayList<IModel<Job>>();
		for (Job job : jobs) {
			modelJobs.add(new LoadableJobModel(job));
		}
		return modelJobs;
	}

	@SuppressWarnings("serial")
	public List<MenuItem> prepare() {
		MenuItem addJobItem = new MenuItem("Add job",
				ManageActivityPage.class) {

			@Override
			public Component createMenu() {
				Link link = new Link("link") {

					@Override
					public void onClick() {
						setResponsePage(new ManageJobPage(
								(SelectableActivity) m_actModel.getObject()));
					}
				};

				link.add(new Label("caption", getCaption()));
				return link;
			}
		};
		return Arrays.asList(addJobItem);
	}
}
